package com.meiyuetao.myt.job;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import lab.s2jh.core.annotation.MetaData;
import lab.s2jh.core.util.DateUtils;
import lab.s2jh.core.web.json.HibernateAwareObjectMapper;
import lab.s2jh.ctx.DynamicConfigService;
import lab.s2jh.ctx.FreemarkerService;
import lab.s2jh.ctx.MailService;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.json.simple.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.meiyuetao.myt.core.constant.MessageStateEnum;
import com.meiyuetao.myt.core.entity.RC4Entity;
import com.meiyuetao.myt.customer.dao.SmsDetailLogDao;
import com.meiyuetao.myt.customer.dao.SmsLogDao;
import com.meiyuetao.myt.customer.entity.CustomerProfile;
import com.meiyuetao.myt.customer.entity.InactiveUser;
import com.meiyuetao.myt.customer.entity.PushCommodityInfo;
import com.meiyuetao.myt.customer.entity.SmsDetailLog;
import com.meiyuetao.myt.customer.entity.SmsDetailLog.SmsDetailChannelEnum;
import com.meiyuetao.myt.customer.entity.SmsLog;
import com.meiyuetao.myt.customer.entity.SmsLog.SmsChannelEnum;
import com.meiyuetao.myt.customer.service.PushCommodityInfoService;
import com.meiyuetao.myt.customer.service.SmsDetailLogService;
import com.meiyuetao.myt.partner.entity.PurchaseCode;
import com.meiyuetao.myt.purchase.entity.PurchaseReceipt;
import com.meiyuetao.myt.sale.entity.BoxOrder;
import com.meiyuetao.myt.sale.entity.BoxOrderDetail;
import com.meiyuetao.myt.sale.entity.SaleDelivery;
import com.meiyuetao.myt.sale.service.BoxOrderDetailCommodityService;

@Service
@Transactional
public class BusinessNotifyService {

    @Autowired
    private FreemarkerService freemarkerService;
    @Autowired
    private SmsDetailLogService smsDetailLogService;
    @Autowired
    private MailService mailService;
    @Autowired
    private DynamicConfigService dynamicConfigService;
    @Autowired
    private BoxOrderDetailCommodityService boxOrderDetailCommodityService;
    @Autowired
    private PushCommodityInfoService pushCommodityInfoService;

    @Autowired
    private SmsDetailLogDao smsDetailLogDao;
    @Autowired
    private SmsLogDao smsLogDao;

    private static int MAX_TRY = 3;
    @Value("${cfg.myt.sms.url}")
    private String smsUrl;
    @Value("${cfg.rc4.key}")
    private String key;

    public enum SMSTypeEnum {
        @MetaData(value = "文本验证码")
        VALIDATION,

        @MetaData(value = "语音验证码")
        VOICE_VALIDATION,

        @MetaData(value = "营销信息")
        TEXT,

        @MetaData(value = "订单推送")
        ORDER,

        @MetaData(value = "其他发送类型")
        TEE;
    }

    /**
     * 云片短信通讯接口
     * 
     * @param mobilePhone
     *            发送手机号
     * @param templateId
     *            使用模板
     * @param content
     *            匹配内容
     * @param smsLog
     */
    public void sendSmsByYunPian(String mobilePhone, String templateId, String content) {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("phone", mobilePhone);
        map.put("templateId", templateId);
        map.put("data", new ArrayList<String>());
        map.put("Type", SMSTypeEnum.TEXT.toString());
        map.put("Verification", content);
        map.put("ExpirationTime", "");
        map.put("TipNumber", "");
        map.put("displayNumber", "");
        String smsStr = JSONObject.toJSONString(map);
        String params = RC4Entity.encry_RC4_string(smsStr, key);

        SmsDetailLog smsDetailLog = smsDetailLogService.findFirstByProperty("mobile", mobilePhone);
        SmsLog smsLog = null;
        if (smsDetailLog == null) {
            smsLog = new SmsLog();
        } else {
            smsLog = smsDetailLog.getSmsLog();
        }
        smsLog.setSendContent(content);
        smsLog.setSendTime(new Date());
        smsLog.setSendToList(mobilePhone);
        smsLog.setSmsChannel(SmsChannelEnum.YP);

        Boolean success = postToMyt(params, smsLog);
        int i = 0;
        while (!success && i < MAX_TRY) {
            success = postToMyt(params, smsLog);
            i++;
        }
    }

    // 云通信 营销短信
    public void sendTextSms(String mobilePhone, String content, SmsLog smsLog) {
        String params = buildParams(mobilePhone, SMSTypeEnum.TEXT, new ArrayList<String>(), content, "", "", "");

        smsLog.setSendContent(content);
        smsLog.setSendTime(new Date());
        smsLog.setSendToList(mobilePhone);
        smsLog.setSmsChannel(SmsChannelEnum.YTX);

        Boolean success = postToMyt(params, smsLog);
        int i = 0;
        while (!success && i < MAX_TRY) {
            success = postToMyt(params, smsLog);
            i++;
        }
    }

    // 云通信 营销短信(定时任务)
    public void sendTextSms(String mobilePhone, String content) {
        String params = buildParams(mobilePhone, SMSTypeEnum.TEXT, new ArrayList<String>(), content, "", "", "");

        SmsDetailLog smsDetailLog = smsDetailLogService.findFirstByProperty("mobile", mobilePhone);
        SmsLog smsLog = null;
        if (smsDetailLog == null) {
            smsLog = new SmsLog();
        } else {
            smsLog = smsDetailLog.getSmsLog();
        }
        smsLog.setSendContent(content);
        smsLog.setSendTime(new Date());
        smsLog.setSendToList(mobilePhone);
        smsLog.setSmsChannel(SmsChannelEnum.YTX);

        Boolean success = postToMyt(params, smsLog);
        int i = 0;
        while (!success && i < MAX_TRY) {
            success = postToMyt(params, smsLog);
            i++;
        }
    }

    private String buildParams(String phone, SMSTypeEnum type, List<String> data, String verification, String expirationTime, String tipNumber, String displayNumber) {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("phone", phone);
        // 订单14339 营销：9 文本验证码ID:14340 语音验证码：2
        String templateId = "";
        if (type.equals(SMSTypeEnum.ORDER)) {
            templateId = "14339";
        } else if (type.equals(SMSTypeEnum.VALIDATION)) {
            templateId = "14340";
        } else if (type.equals(SMSTypeEnum.TEXT)) {
            templateId = "9";
        } else if (type.equals(SMSTypeEnum.VOICE_VALIDATION)) {
            templateId = "2";
        }
        map.put("templateId", templateId);
        map.put("data", data == null ? new ArrayList<String>() : data);
        map.put("Type", type.toString());
        map.put("Verification", verification);
        map.put("ExpirationTime", expirationTime);
        map.put("TipNumber", tipNumber);
        map.put("displayNumber", displayNumber);
        String smsStr = JSONObject.toJSONString(map);
        String params = RC4Entity.encry_RC4_string(smsStr, key);
        System.out.println("params:" + smsStr);
        System.out.println("params rc4:" + params);
        return params;
    }

    private boolean postToMyt(String paramsValue, SmsLog smsLog) {
        HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
        CloseableHttpClient httpClient = httpClientBuilder.build();
        HttpPost httpPost = new HttpPost(smsUrl);
        System.out.println("SMSURL:" + smsUrl);
        List<NameValuePair> params = new ArrayList<NameValuePair>();
        params.add(new BasicNameValuePair("Params", paramsValue));
        String response = null;
        try {
            HttpEntity entity = new UrlEncodedFormEntity(params, "UTF-8");
            httpPost.setEntity(entity);
            HttpResponse httpResponse;
            // post请求
            httpResponse = httpClient.execute(httpPost);
            HttpEntity httpEntity = httpResponse.getEntity();
            if (httpEntity != null) {
                response = EntityUtils.toString(httpEntity, "UTF-8");
                System.out.println("SMS Response：" + response);
            }
            httpClient.close();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        boolean flag = false;
        if (StringUtils.isNotBlank(response)) {
            ObjectMapper objectMapper = HibernateAwareObjectMapper.getInstance();
            Map<String, String> statusMap = new HashMap<String, String>();
            try {
                statusMap = objectMapper.readValue(response, Map.class);
            } catch (Exception e) {
                e.printStackTrace();
            }

            // 记录日志
            SmsDetailLog smsDetailLog = new SmsDetailLog();
            smsDetailLog.setContent(smsLog.getSendContent());
            smsDetailLog.setMobile(smsLog.getSendToList());
            smsDetailLog.setSendTime(new Date());
            smsDetailLog.setSmsLog(smsLog);
            smsDetailLog.setSmsChannel(SmsDetailChannelEnum.valueOf(smsLog.getSmsChannel().toString()));
            smsLogDao.save(smsLog);
            smsDetailLog.setMemo(statusMap.get("statusMsg"));

            if (String.valueOf(statusMap.get("statusCode")).equals("000000")) {
                flag = true;
                smsDetailLog.setState(MessageStateEnum.OK);
            } else {
                smsDetailLog.setState(MessageStateEnum.FAIL);
            }
            smsDetailLogDao.save(smsDetailLog);
        }
        return flag;
    }

    // 客户付款通知邮件
    public void sendPayNotifyEmail(BoxOrderDetail boxOrderDetail) {

        Map<String, Object> dataMap = new HashMap<String, Object>();
        CustomerProfile customerProfile = boxOrderDetail.getBoxOrder().getCustomerProfile();
        dataMap.put("boxOrderDetail", boxOrderDetail);
        dataMap.put("customerProfile", customerProfile);
        dataMap.put("boxOrder", boxOrderDetail.getBoxOrder());
        dataMap.put("boxOrderDetailCommodities", boxOrderDetail.getBoxOrderDetailCommodities());
        dataMap.put("todayDate", new Date());
        dataMap.put("reserveDeliveryTime", boxOrderDetail.getReserveDeliveryTime());
        String emailContent = freemarkerService.processTemplateByFileName("PAY_NOTIFY_EMAIL", dataMap);
        String emailAddr = boxOrderDetail.getBoxOrder().getCustomerProfile().getEmail();
        if (StringUtils.isNotBlank(emailAddr)) {
            mailService.sendHtmlMail("您有一笔未付款订单", emailContent, false, emailAddr);
        }
    }

    // 客户付款通知短信
    public void sendPayNotifySms(BoxOrderDetail boxOrderDetail) {
        Map<String, Object> dataMap = new HashMap<String, Object>();
        dataMap.put("boxOrder", boxOrderDetail.getBoxOrder());
        // dataMap.put("customerProfile", boxOrderDetail.getCustomerProfile());
        String smsContent = freemarkerService.processTemplateByFileName("PAY_NOTIFY_SMS", dataMap);
        String mobilePhone = boxOrderDetail.getCustomerProfile().getMobilePhone();
        if (StringUtils.isNotBlank(smsContent) && StringUtils.isNotBlank(mobilePhone)) {
            sendMsgAsync(mobilePhone.trim(), smsContent);
        }
    }

    // 发货通知邮件
    public void sendDeliveryNotifyEmail(SaleDelivery saleDelivery) {
        Map<String, Object> dataMap = new HashMap<String, Object>();
        dataMap.put("saleDelivery", saleDelivery);
        dataMap.put("saleDeliveryDetails", saleDelivery.getSaleDeliveryDetails());
        dataMap.put("customerProfile", saleDelivery.getCustomerProfile());
        dataMap.put("todayDate", new Date());
        String emailContent = freemarkerService.processTemplateByFileName("DELIVERY_NOTIFY_EMAIL", dataMap);
        String emailAddr = saleDelivery.getCustomerProfile().getEmail();
        if (StringUtils.isNotBlank(emailAddr)) {
            mailService.sendHtmlMail("发货通知", emailContent, false, emailAddr);
        }
    }

    // 发推送邮件
    public void sendPushNotifyEmail(InactiveUser user, String eoe, String passwordText) {
        Map<String, Object> dataMap = new HashMap<String, Object>();
        List<PushCommodityInfo> list = pushCommodityInfoService.findByFilters(null);
        if (StringUtils.isNotBlank(eoe)) {
            dataMap.put("pfix", "亲爱的" + user.getName() + " 您" + eoe + "送了您一张美月淘母婴商城的50元购物券，登录http://m.meiyuetao.com/使用，");
        } else {
            dataMap.put("pfix", "亲爱的" + user.getName() + " 我们送了您一张美月淘母婴商城的50元购物券，登录http://m.meiyuetao.com/使用，");
        }
        dataMap.put("sfix", "用户名为您的手机号：" + user.getMobile() + " 初始密码：" + passwordText);
        dataMap.put("list", list);

        String emailContent = freemarkerService.processTemplateByFileName("USER_PUSH_NOTIFY_EMAIL", dataMap);
        String emailAddr = user.getEmail();
        if (StringUtils.isNotBlank(emailAddr)) {
            mailService.sendHtmlMail("商品推送", emailContent, false, emailAddr);
        }
    }

    // 订单取消通知邮件
    public void sendOrderCancelNotifyEmail(BoxOrder boxOrder) {
        Map<String, Object> dataMap = new HashMap<String, Object>();
        dataMap.put("boxOrder", boxOrder);
        dataMap.put("customerProfile", boxOrder.getCustomerProfile());
        dataMap.put("todayDate", new Date());
        String emailContent = freemarkerService.processTemplateByFileName("ORDER_CANCEL_NOTIFY_EMAIL", dataMap);
        String emailAddr = boxOrder.getCustomerProfile().getEmail();
        if (StringUtils.isNotBlank(emailAddr)) {
            mailService.sendHtmlMail("订单取消", emailContent, false, emailAddr);
        }
    }

    // 异步
    @Async
    public void sendOrderCancelNotifyEmailAsync(BoxOrder boxOrder) {
        sendOrderCancelNotifyEmail(boxOrder);
    }

    // 消费码通知邮件
    public void sendPurchaseCodeNotifyEmail(List<PurchaseCode> purchaseCodes, BoxOrder boxOrder, BoxOrderDetail boxOrderDetail) {
        if (boxOrderDetail != null) {
            boxOrder = boxOrderDetail.getBoxOrder();
        }
        Map<String, Object> dataMap = new HashMap<String, Object>();
        dataMap.put("boxOrder", boxOrder);
        dataMap.put("customerProfile", boxOrder.getCustomerProfile());
        dataMap.put("purchaseCodes", purchaseCodes);
        dataMap.put("todayDate", DateUtils.formatDate(new Date()));
        String emailContent = freemarkerService.processTemplateByFileName("PURCHASE_CODE_NOTIFY_EMAIL", dataMap);
        String emailAddr = boxOrder.getCustomerProfile().getEmail();
        if (StringUtils.isNotBlank(emailAddr)) {
            mailService.sendHtmlMail("服务商品的消费码", emailContent, false, emailAddr);
        }
    }

    @Async
    public void sendPurchaseReceiptEmailAsync(PurchaseReceipt purchaseReceipt) {
        sendPurchaseReceiptEmail(purchaseReceipt);
    }

    // 收货入库通知邮件
    public void sendPurchaseReceiptEmail(PurchaseReceipt purchaseReceipt) {
        String emailList = dynamicConfigService.getString("cfg.mail.purchase.receipt", "");
        Map<String, Object> dataMap = new HashMap<String, Object>();
        dataMap.put("purchaseReceipt", purchaseReceipt);
        dataMap.put("purchaseReceiptDetails", purchaseReceipt.getPurchaseReceiptDetails());
        String emailContent = freemarkerService.processTemplateByFileName("PUCHASE_RECEIPT_NOTIFY_EMAIL", dataMap);
        if (StringUtils.isNotBlank(emailList)) {
            String[] emails = emailList.replace("，", ",").replace(";", ",").split(",");
            mailService.sendHtmlMail("收货入库", emailContent, false, emails);
        }
    }

    // 三通（TEE）
    @Async
    public void sendMsgAsync(String mobilePhone, String content) {
        String params = buildParams(mobilePhone, SMSTypeEnum.TEE, new ArrayList<String>(), content, "", "", "");

        SmsDetailLog smsDetailLog = smsDetailLogService.findFirstByProperty("mobile", mobilePhone);
        SmsLog smsLog = null;
        if (smsDetailLog == null) {
            smsLog = new SmsLog();
        } else {
            smsLog = smsDetailLog.getSmsLog();
        }
        smsLog.setSendContent(content);
        smsLog.setSendTime(new Date());
        smsLog.setSendToList(mobilePhone);
        smsLog.setSmsChannel(SmsChannelEnum.STONG);

        Boolean success = postToMyt(params, smsLog);
        int i = 0;
        while (!success && i < MAX_TRY) {
            success = postToMyt(params, smsLog);
            i++;
        }
    }

    // 三通（TEE）
    @Async
    public void sendMsgAsync(String mobilePhone, String content, SmsLog smsLog) {
        String params = buildParams(mobilePhone, SMSTypeEnum.TEE, new ArrayList<String>(), content, "", "", "");

        smsLog.setSendContent(content);
        smsLog.setSendTime(new Date());
        smsLog.setSendToList(mobilePhone);
        smsLog.setSmsChannel(SmsChannelEnum.STONG);

        Boolean success = postToMyt(params, smsLog);
        int i = 0;
        while (!success && i < MAX_TRY) {
            success = postToMyt(params, smsLog);
            i++;
        }
    }

    // 三通（TEE）
    public void sendMsg(String mobilePhone, String content) {
        String params = buildParams(mobilePhone, SMSTypeEnum.TEE, new ArrayList<String>(), content, "", "", "");

        SmsDetailLog smsDetailLog = smsDetailLogService.findFirstByProperty("mobile", mobilePhone);
        SmsLog smsLog = null;
        if (smsDetailLog == null) {
            smsLog = new SmsLog();
        } else {
            smsLog = smsDetailLog.getSmsLog();
        }
        smsLog.setSendContent(content);
        smsLog.setSendTime(new Date());
        smsLog.setSendToList(mobilePhone);
        smsLog.setSmsChannel(SmsChannelEnum.STONG);

        Boolean success = postToMyt(params, smsLog);
        int i = 0;
        while (!success && i < MAX_TRY) {
            success = postToMyt(params, smsLog);
            i++;
        }
    }

    /*
     * @Async public void sendMsgAsync(String mobilePhone, String content) {
     * SmsDetailLog smsDetailLog =
     * smsDetailLogService.findFirstByProperty("mobile", mobilePhone); SmsLog
     * smsLog = null; if (smsDetailLog == null) { smsLog = new SmsLog(); } else
     * { smsLog = smsDetailLog.getSmsLog(); } smsLog.setSendContent(content);
     * smsLog.setSendTime(new Date()); smsLog.setSendToList(mobilePhone);
     * smsLog.setSmsChannel(SmsChannelEnum.STONG); Boolean success =
     * threeTongSmsService.send(mobilePhone, content, smsLog); int i = 0; while
     * (!success && i < MAX_TRY) { success =
     * threeTongSmsService.send(mobilePhone, content, smsLog); i++; } }
     */

    /*
     * public void sendMsg(String mobilePhone, String content) { SmsDetailLog
     * smsDetailLog = smsDetailLogService.findFirstByProperty("mobile",
     * mobilePhone); SmsLog smsLog = null; if (smsDetailLog == null) { smsLog =
     * new SmsLog(); } else { smsLog = smsDetailLog.getSmsLog(); }
     * smsLog.setSendContent(content); smsLog.setSendTime(new Date());
     * smsLog.setSendToList(mobilePhone);
     * smsLog.setSmsChannel(SmsChannelEnum.STONG); Boolean success =
     * threeTongSmsService.send(mobilePhone, content, smsLog); int i = 0; while
     * (!success && i < MAX_TRY) { success =
     * threeTongSmsService.send(mobilePhone, content, smsLog); i++; } }
     */

    private final static Logger logger = LoggerFactory.getLogger(BusinessNotifyService.class);

    @Async
    public void cpsSendAsync(BoxOrder boxOrder) {
        HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
        CloseableHttpClient client = httpClientBuilder.build();
        HttpPost httpPost = new HttpPost(dynamicConfigService.getString("cfg.cps.orderUrl"));
        List<NameValuePair> formparams = new ArrayList<NameValuePair>();
        formparams.add(new BasicNameValuePair("order_id", String.valueOf(boxOrder.getId())));
        String response = null;
        try {
            UrlEncodedFormEntity urlEncodedFormEntity = new UrlEncodedFormEntity(formparams, "UTF-8");
            httpPost.setEntity(urlEncodedFormEntity);
            HttpResponse httpResponse;
            // post请求
            httpResponse = client.execute(httpPost);
            HttpEntity httpEntity = httpResponse.getEntity();
            int i = 0;
            while (i < MAX_TRY && httpEntity == null) {
                httpEntity = httpResponse.getEntity();
                i++;
            }
            if (httpEntity != null) {
                response = EntityUtils.toString(httpEntity, "UTF-8");
            }
            client.close();
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }

    }

    public String getSmsUrl() {
        return smsUrl;
    }

    public void setSmsUrl(String smsUrl) {
        this.smsUrl = smsUrl;
    }

    public String getKey() {
        return key;
    }

    public void setKey(String key) {
        this.key = key;
    }

}
